using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Xml.XPath;

namespace MapTestFramework.Common.Tests
{
    [TestClass]
    public class XmlHelperFixture
    {
        #region Constructor And Initializing Members

        public XmlHelperFixture()
        {
            return;
        }

        #endregion

        #region Additional test attributes

        #endregion

        #region Test Members

        #region GetSingleNode

        [TestMethod]
        public void GetSingleNodeSingleHit()
        {
            ExecuteGetSingleNodeTest(
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']/*[local-name()='Field_OneToOne' and namespace-uri()='']",
                "Field_OneToOne_0"
                );
            return;
        }
        [TestMethod]
        public void GetSingleNodeMultipleHits()
        {
            ExecuteGetSingleNodeTest(
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_MultipleHits' and namespace-uri()='']/*[local-name()='Field_OneToOne_MultipleHits' and namespace-uri()='']",
                "Field_OneToOne_MultipleHits_0"
                );
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(MapTestException))]
        public void GetSingleNodeNoHit()
        {
            string xpath = "NonExisting";
            try
            {
                ExecuteGetSingleNodeTest(xpath);
            }
            catch (MapTestException ex)
            {
                Assert.AreEqual(
                    string.Format("No node for XPath expression '{0}'", xpath),
                    ex.Message, "Invalid exception message."
                    );
                throw ex;
            }
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void GetSingleNodeSourcePathNull()
        {
            this.SourcePathBase = null;
            try
            {
                ExecuteGetSingleNodeTest(
                    "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Field_OneToOne_MultipleHits' and namespace-uri()='']"
                    );
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("sourcePath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: sourcePath",
                    ex.Message, "Invalid exception message."
                    );
                throw ex;
            }
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void GetSingleNodeSourcePathEmpty()
        {
            this.SourcePathBase = string.Empty;
            try
            {
                ExecuteGetSingleNodeTest(
                    "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Field_OneToOne_MultipleHits' and namespace-uri()='']"
                    );
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("sourcePath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: sourcePath",
                    ex.Message, "Invalid exception message."
                    );
                throw ex;
            }
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(XPathException))]
        public void GetSingleNodeXPathNull()
        {
            string xpath = null;
            try
            {
                ExecuteGetSingleNodeTest(xpath);
            }
            catch (ArgumentNullException ex)
            {
                Assert.AreEqual("xpath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null.\r\nParameter name: xpath",
                    ex.Message, "Invalid exception message."
                    );
                throw ex;
            }
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void GetSingleNodeSourceNull()
        {
            XmlDocument source = null;
            try
            {
                ExecuteGetSingleNodeTest(source);
            }
            catch (ArgumentNullException ex)
            {
                Assert.AreEqual("source", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null.\r\nParameter name: source",
                    ex.Message, "Invalid exception message."
                    );
                throw ex;
            }
            return;
        }

        #endregion

        #region GetAllNodes

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void GetAllNodesSourcePathNull()
        {
            string sourcePath = null;
            try
            {
                ExecuteGetAllNodesTest(sourcePath);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("sourcePath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: sourcePath",
                    ex.Message, "Invalid exception message."
                    );
                throw;
            }
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void GetAllNodesSourcePathEmpty()
        {
            string sourcePath = string.Empty;
            try
            {
                ExecuteGetAllNodesTest(sourcePath);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("sourcePath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: sourcePath",
                    ex.Message, "Invalid exception message."
                    );
                throw;
            }
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void GetAllNodesSourceNull()
        {
            XmlDocument source = null;
            try
            {
                ExecuteGetAllNodesTest(source);
            }
            catch (ArgumentNullException ex)
            {
                Assert.AreEqual("source", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null.\r\nParameter name: source",
                    ex.Message, "Invalid exception message."
                    );
                throw ex;
            }
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(XPathException))]
        public void GetAllNodesXPathNull()
        {
            XmlDocument source = new XmlDocument();
            source.Load(this.SourcePathBase);
            ExecuteGetAllNodesTest(source, null);
            return;
        }
        [TestMethod]
        public void GetAllNodesSingleHit()
        {
            ExecuteGetAllNodesTest(
                "Schema1.xml",
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']/*[local-name()='Field_OneToOne' and namespace-uri()='']",
                new string[] { 
                    "Field_OneToOne_0"
                    }
                );
            return;
        }
        [TestMethod]
        public void GetAllNodesMultipleHits()
        {
            ExecuteGetAllNodesTest(
                "Schema1.xml",
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_MultipleHits' and namespace-uri()='']/*[local-name()='Field_OneToOne_MultipleHits' and namespace-uri()='']",
                new string[] { 
                    "Field_OneToOne_MultipleHits_0",
                    "Field_OneToOne_MultipleHits_1",
                    "Field_OneToOne_MultipleHits_2"
                    }
                );
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(MapTestException))]
        public void GetAllNodesNoHit()
        {
            string xpath = "NonExisting";
            try
            {
                ExecuteGetAllNodesTest("Schema1.xml", xpath);
            }
            catch (MapTestException ex)
            {
                Assert.AreEqual(
                    string.Format("No node for XPath expression '{0}'", xpath),
                    ex.Message, "Invalid exception message."
                    );
                throw ex;
            }
            return;
        }

        #endregion

        #region RemoveNodes with XPath array parameter

        [TestMethod]
        public void RemoveNodesXPathArrayXPathsSingle()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']"
                };
            ExecuteRemoveTest(xpaths);
            return;
        }
        [TestMethod]
        public void RemoveNodesXPathArrayXPathsSingleAttribute()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']/@*[local-name()='Attribute_OneToOne' and namespace-uri()='']",
                };
            ExecuteRemoveTest(xpaths);
            return;
        }
        [TestMethod]
        public void RemoveNodesXPathArrayXPathsSingleMultipleHits()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_MultipleHits' and namespace-uri()='']/*[local-name()='Field_OneToOne_MultipleHits' and namespace-uri()='']"
                };
            ExecuteRemoveTest(xpaths);
            return;
        }
        [TestMethod]
        public void RemoveNodesXPathArrayXPathsMultiple()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']/@*[local-name()='Attribute_OneToOne' and namespace-uri()='']",
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']/*[local-name()='Field_OneToOne' and namespace-uri()='']"
                };
            ExecuteRemoveTest(xpaths);
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(MapTestException))]
        public void RemoveNodesXPathArrayXPathsInvalid()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']",
                "",
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Child2' and namespace-uri()='']"
                };
            try
            {
                ExecuteRemoveTest(xpaths);
            }
            catch (MapTestException ex)
            {
                Assert.AreEqual("Invalid XPath expression ''", 
                    ex.Message, "Invalid exception message."
                    );
                Assert.IsNotNull(ex.InnerException);
                Assert.IsInstanceOfType(ex.InnerException, typeof(XPathException));
                
                Assert.IsFalse(
                    File.Exists(GetOutputPath()), "Outputfile was created."
                    );
                throw;
            }
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(MapTestException))]
        public void RemoveNodesXPathArrayXPathsNoNodes()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='NonExisting' and namespace-uri()='http://MySampleProject.Schemas.Schema1']"
                };
            try
            {
                ExecuteRemoveTest(xpaths);
            }
            catch (MapTestException ex)
            {
                Assert.AreEqual(
                    string.Format("No node for XPath expression '{0}'", xpaths[0]), 
                    ex.Message, "Invalid exception message."
                    );
                Assert.IsFalse(
                    File.Exists(GetOutputPath()), "Outputfile was created."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void RemoveNodesXPathArrayXPathsNull()
        {
            try
            {
                string[] xpaths = null;
                ExecuteRemoveTest(xpaths);
            }
            catch (ArgumentNullException ex)
            {
                Assert.AreEqual("xpaths", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null.\r\nParameter name: xpaths",
                    ex.Message, "Invalid exception message."
                    );
                Assert.IsFalse(
                    File.Exists(GetOutputPath()), "Outputfile was created."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void RemoveNodesXPathArraySourcePathNull()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']"
                };
            SourcePathBase = null;
            try
            {
                ExecuteRemoveTest(xpaths);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("sourcePath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: sourcePath",
                    ex.Message, "Invalid exception message."
                    );
                Assert.IsFalse(
                    File.Exists(GetOutputPath()), "Outputfile was created."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void RemoveNodesXPathArraySourcePathEmpty()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']"
                };
            SourcePathBase = string.Empty;
            try
            {
                ExecuteRemoveTest(xpaths);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("sourcePath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: sourcePath",
                    ex.Message, "Invalid exception message."
                    );
                Assert.IsFalse(
                    File.Exists(GetOutputPath()), "Outputfile was created."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void RemoveNodesXPathArrayOutputPathNull()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']"
                };
            try
            {
                ExecuteRemoveTest(xpaths, null);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("outputPath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: outputPath",
                    ex.Message, "Invalid exception message."
                    );
                Assert.IsFalse(
                    File.Exists(GetOutputPath()), "Outputfile was created."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void RemoveNodesXPathArrayOutputPathEmpty()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']"
                };
            try
            {
                ExecuteRemoveTest(xpaths, string.Empty);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("outputPath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: outputPath",
                    ex.Message, "Invalid exception message."
                    );
                Assert.IsFalse(
                    File.Exists(GetOutputPath()), "Outputfile was created."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void RemoveNodesXPathArrayDocumentNull()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']"
                };
            try
            {
                ExecuteRemoveTest(null, xpaths);
            }
            catch (ArgumentNullException ex)
            {
                Assert.AreEqual("source", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null.\r\nParameter name: source",
                    ex.Message, "Invalid exception message."
                    );
                Assert.IsFalse(
                    File.Exists(GetOutputPath()), "Outputfile was created."
                    );
                throw;
            }

            return;
        }

        #endregion

        #region RemoveNodes with XPath string parameter

        [TestMethod]
        public void RemoveNodesXPathString()
        {
            string xpath = "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']";
            ExecuteRemoveTest(xpath);
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(XPathException))]
        public void RemoveNodesXPathStringXPathNull()
        {
            string xpath = null;
            ExecuteRemoveTest(xpath);
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void RemoveNodesXPathStringSourcePathNull()
        {
            string xpath = "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']";
            SourcePathBase = null;
            try
            {
                ExecuteRemoveTest(xpath);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("sourcePath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: sourcePath",
                    ex.Message, "Invalid exception message."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void RemoveNodesXPathStringSourcePathEmpty()
        {
            try
            {
                string xpath = "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']";
                SourcePathBase = string.Empty;
                ExecuteRemoveTest(xpath);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("sourcePath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: sourcePath",
                    ex.Message, "Invalid exception message."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void RemoveNodesXPathStringOutputPathNull()
        {
            string xpath = "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']";
            string outputPath = null;
            try
            {
                ExecuteRemoveTest(xpath, outputPath);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("outputPath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: outputPath",
                    ex.Message, "Invalid exception message."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void RemoveNodesXPathStringOutputPathEmpty()
        {
            string xpath = "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']";
            try
            {
                ExecuteRemoveTest(xpath, string.Empty);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("outputPath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: outputPath",
                    ex.Message, "Invalid exception message."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void RemoveNodesXPathStringSourceNull()
        {
            try
            {
                string xpath = "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']";
                XmlDocument source = null;
                ExecuteRemoveTest(xpath, source);
            }
            catch (ArgumentNullException ex)
            {
                Assert.AreEqual("source", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null.\r\nParameter name: source",
                    ex.Message, "Invalid exception message."
                    );
                throw;
            }

            return;
        }

        #endregion

        #region UpdateNodes with XPath array parameter

        [TestMethod]
        public void UpdateNodesXPathArrayXPathsSingle()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']/*[local-name()='Field_OneToOne' and namespace-uri()='']"
                };
            string[] values = new string[] {
                "Value1"
                };
            ExecuteUpdateTest(xpaths, values);
            return;
        }
        [TestMethod]
        public void UpdateNodesXPathArrayXPathsSingleAttribute()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']/@*[local-name()='Attribute_OneToOne' and namespace-uri()='']"
                };
            string[] values = new string[] {
                "Value1"
                };
            ExecuteUpdateTest(xpaths, values);
            return;
        }
        [TestMethod]
        public void UpdateNodesXPathArrayXPathsSingleValueNull()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_MultipleHits' and namespace-uri()='']/*[local-name()='Field_OneToOne_MultipleHits' and namespace-uri()='']"
                };
            string[] values = new string[1];
            ExecuteUpdateTest(xpaths, values);
            return;
        }
        [TestMethod]
        public void UpdateNodesXPathArrayXPathsSingleMultipleHits()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_MultipleHits' and namespace-uri()='']/*[local-name()='Field_OneToOne_MultipleHits' and namespace-uri()='']"
                };
            string[] values = new string[] {
                "Field_OneToOne_MultipleHits_1"
                };
            ExecuteUpdateTest(xpaths, values);
            return;
        }
        [TestMethod]
        public void UpdateNodesXPathArrayXPathsMultiple()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']/*[local-name()='Field_OneToOne' and namespace-uri()='']",
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']/@*[local-name()='Attribute_OneToOne' and namespace-uri()='']"
                };
            string[] values = new string[] {
                "Value1",
                "Value2"
                };
            ExecuteUpdateTest(xpaths, values);
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(MapTestException))]
        public void UpdateNodesXPathArrayXPathsInvalid()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']",
                "",
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Child2' and namespace-uri()='']"
                };
            string[] values = new string[] {
                "Value1",
                "Value2",
                "Value3"
                };
            try
            {
                ExecuteUpdateTest(xpaths, values);
            }
            catch (MapTestException ex)
            {
                Assert.AreEqual("Invalid XPath expression ''",
                    ex.Message, "Invalid exception message."
                    );
                Assert.IsFalse(
                    File.Exists(GetOutputPath()), "Outputfile was created."
                    );
                throw;
            }
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(MapTestException))]
        public void UpdateNodesXPathArrayXPathsNoNodes()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='NonExisting' and namespace-uri()='http://MySampleProject.Schemas.Schema1']"
                };
            string[] values = new string[] {
                "Value1"
                };
            try
            {
                ExecuteUpdateTest(xpaths, values);
            }
            catch (MapTestException ex)
            {
                Assert.AreEqual(
                    string.Format("No node for XPath expression '{0}'", xpaths[0]),
                    ex.Message, "Invalid exception message."
                    );
                Assert.IsFalse(
                    File.Exists(GetOutputPath()), "Outputfile was created."
                    );
                throw;
            }
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void UpdateNodesXPathArrayXPathsNull()
        {
            string[] xpaths = null;
            string[] values = new string[] {
                "Value1"
                };
            try
            {
                ExecuteUpdateTest(xpaths, values);
            }
            catch (ArgumentNullException ex)
            {
                Assert.AreEqual("xpaths", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null.\r\nParameter name: xpaths",
                    ex.Message, "Invalid exception message."
                    );
                Assert.IsFalse(
                    File.Exists(GetOutputPath()), "Outputfile was created."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void UpdateNodesXPathArraySourcePathNull()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']"
                };
            string[] values = new string[] {
                "Value1"
                };

            SourcePathBase = null;
            try
            {
                ExecuteUpdateTest(xpaths, values);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("sourcePath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: sourcePath",
                    ex.Message, "Invalid exception message."
                    );
                Assert.IsFalse(
                    File.Exists(GetOutputPath()), "Outputfile was created."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void UpdateNodesXPathArraySourcePathEmpty()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']"
                };
            string[] values = new string[] {
                "Value1"
                };
            SourcePathBase = string.Empty;
            try
            {
                ExecuteUpdateTest(xpaths, values);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("sourcePath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: sourcePath",
                    ex.Message, "Invalid exception message."
                    );
                Assert.IsFalse(
                    File.Exists(GetOutputPath()), "Outputfile was created."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void UpdateNodesXPathArrayOutputPathNull()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']"
                };
            string[] values = new string[] {
                "Value1"
                };
            try
            {
                ExecuteUpdateTest(xpaths, values, null);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("outputPath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: outputPath",
                    ex.Message, "Invalid exception message."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void UpdateNodesXPathArrayOutputPathEmpty()
        {
            string[] xpaths = new string[] {
                "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']"
                };
            string[] values = new string[] {
                "Value1"
                };
            try
            {
                ExecuteUpdateTest(xpaths, values, string.Empty);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("outputPath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: outputPath",
                    ex.Message, "Invalid exception message."
                    );
                throw;
            }

            return;
        }

        #endregion

        #region UpdateNodes with XPath string parameter

        [TestMethod]
        public void UpdateNodesXPathString()
        {
            string xpath = "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']/*[local-name()='Field_OneToOne' and namespace-uri()='']";
            ExecuteUpdateTest(xpath, "Field_OneToOne_1");
            return;
        }
        [TestMethod]
        public void UpdateNodesXPathStringNull()
        {
            string xpath = "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']/*[local-name()='Field_OneToOne' and namespace-uri()='']";
            ExecuteUpdateTest(xpath, null);
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(MapTestException))]
        public void UpdateNodesXPathStringXPathNull()
        {
            try
            {
                string xpath = null;
                ExecuteUpdateTest(xpath, string.Empty);
            }
            catch (MapTestException ex)
            {
                Assert.AreEqual(
                    "Invalid XPath expression ''",
                    ex.Message, "Invalid exception message."
                    );
                throw;
            }
            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void UpdateNodesXPathStringSourcePathNull()
        {
            string xpath = "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']/*[local-name()='Field_OneToOne' and namespace-uri()='']";
            SourcePathBase = null;
            try
            {
                ExecuteUpdateTest(xpath, string.Empty);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("sourcePath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: sourcePath",
                    ex.Message, "Invalid exception message."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void UpdateNodesXPathStringSourcePathEmpty()
        {
            string xpath = "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']";
            SourcePathBase = string.Empty;
            try
            {
                ExecuteUpdateTest(xpath, string.Empty);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("sourcePath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: sourcePath",
                    ex.Message, "Invalid exception message."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void UpdateNodesXPathStringOutputPathNull()
        {
            string xpath = "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']";
            string outputPath = null;
            try
            {
                ExecuteUpdateTest(xpath, string.Empty, outputPath);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("outputPath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: outputPath",
                    ex.Message, "Invalid exception message."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void UpdateNodesXPathStringOutputPathEmpty()
        {
            string xpath = "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']";
            try
            {
                ExecuteUpdateTest(xpath, string.Empty, string.Empty);
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual("outputPath", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null or empty.\r\nParameter name: outputPath",
                    ex.Message, "Invalid exception message."
                    );
                throw;
            }

            return;
        }
        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void UpdateNodesXPathStringSourceNull()
        {
            try
            {
                string xpath = "/*[local-name()='Root' and namespace-uri()='http://MySampleProject.Schemas.Schema1']/*[local-name()='Record_OneToOne_Optional' and namespace-uri()='']";
                XmlDocument source = null;
                ExecuteRemoveTest(xpath, source);
            }
            catch (ArgumentNullException ex)
            {
                Assert.AreEqual("source", ex.ParamName, "Invalid parameter name.");
                Assert.AreEqual(
                    "Value cannot be null.\r\nParameter name: source",
                    ex.Message, "Invalid exception message."
                    );
                throw;
            }

            return;
        }

        #endregion

        #endregion

        #region Helper Members

        private string m_SourcePathBase = "Schema1.xml";
        private string m_TestName = "RemoveNodesTest";

        private string SourcePathBase
        {
            get { return m_SourcePathBase; }
            set { m_SourcePathBase = value; }
        }

        private void ExecuteGetAllNodesTest(string sourcePath)
        {
            this.ExecuteGetAllNodesTest(sourcePath, null);
            return;
        }
        private void ExecuteGetAllNodesTest(string sourcePath, string xpath)
        {
            this.ExecuteGetAllNodesTest(sourcePath, xpath, null);
            return;
        }
        private void ExecuteGetAllNodesTest(string sourcePath, string xpath, string[] expectedValues)
        {
            XPathNodeIterator nodes = XmlHelper.GetAllNodesOrThrowException(
                xpath, sourcePath
                );

            Assert.IsNotNull(nodes, "No nodes found.");
            Assert.AreEqual(nodes.Count, expectedValues.Length);
            while(nodes.MoveNext())
                Assert.AreEqual(expectedValues[nodes.CurrentPosition - 1], nodes.Current.InnerXml,
                    "Invalid InnerText value."
                    );
            return;
        }
        private void ExecuteGetAllNodesTest(XmlDocument source)
        {
            this.ExecuteGetAllNodesTest(source, null);
            return;
        }
        private void ExecuteGetAllNodesTest(XmlDocument source, string xpath)
        {
            XmlHelper.GetAllNodesOrThrowException(xpath, source);
            return;
        }
        private void ExecuteGetSingleNodeTest(XmlDocument source)
        {
            XmlHelper.GetSingleNodeOrThrowException(null, source);
            return;
        }
        private void ExecuteGetSingleNodeTest(string xpath)
        {
            this.ExecuteGetSingleNodeTest(xpath, null);
            return;
        }
        private void ExecuteGetSingleNodeTest(string xpath, string expectedValue)
        {
            XPathNavigator node = XmlHelper.GetSingleNodeOrThrowException(
                xpath, this.SourcePathBase
                );
            Assert.IsNotNull(node, "Node is null.");
            Assert.AreEqual(expectedValue, node.InnerXml, "Invalid InnerText value.");
            return;
        }
        private void ExecuteRemoveTest(XmlDocument source, string[] xpaths)
        {
            XmlHelper.RemoveNodes(xpaths, source);

            foreach (string xpath in xpaths)
            {
                Assert.AreEqual(
                    0, source.SelectNodes(xpath).Count,
                    string.Format("Nodes found for \"{0}\".", xpath)
                    );
            }
            return;
        }
        private void ExecuteRemoveTest(string[] xpaths)
        {
            this.ExecuteRemoveTest(xpaths, this.GetOutputPath());
            return;
        }
        private void ExecuteRemoveTest(string[] xpaths, string outputPath)
        {
            if (File.Exists(outputPath))
                File.Delete(outputPath);

            XmlHelper.RemoveNodes(xpaths, this.SourcePathBase, outputPath);

            XmlDocument outputDocument = new XmlDocument();
            outputDocument.Load(outputPath);

            foreach (string xpath in xpaths)
            {
                Assert.AreEqual(
                    0, outputDocument.SelectNodes(xpath).Count,
                    string.Format("Nodes found for \"{0}\".", xpath)
                    );
            }
            return;
        }
        private void ExecuteRemoveTest(string xpath)
        {
            this.ExecuteRemoveTest(xpath, this.GetOutputPath());
            return;
        }
        private void ExecuteRemoveTest(string xpath, string outputPath)
        {
            if (File.Exists(outputPath))
                File.Delete(outputPath);

            XmlHelper.RemoveNodes(xpath, this.SourcePathBase, outputPath);

            XmlDocument outputDocument = new XmlDocument();
            outputDocument.Load(outputPath);

            Assert.AreEqual(
                0, outputDocument.SelectNodes(xpath).Count,
                string.Format("Nodes found for \"{0}\".", xpath)
                );
            return;
        }
        private void ExecuteRemoveTest(string xpath, XmlDocument source)
        {
            XmlHelper.RemoveNodes(xpath, source);

            Assert.AreEqual(
                0, source.SelectNodes(xpath).Count,
                string.Format("Nodes found for \"{0}\".", xpath)
                );
            return;
        }
        private void ExecuteUpdateTest(string[] xpaths, string[] values)
        {
            m_TestName = "UpdateNodesTest";
            this.ExecuteUpdateTest(xpaths, values, this.GetOutputPath());
            return;
        }
        private void ExecuteUpdateTest(string[] xpaths, string[] values, string outputPath)
        {
            if (File.Exists(outputPath))
                File.Delete(outputPath);

            XmlHelper.UpdateNodes(xpaths, values, this.SourcePathBase, outputPath);

            XmlDocument outputDocument = new XmlDocument();
            outputDocument.Load(outputPath);

            for(int i = 0; i < xpaths.Length; i++)
            {
                if (values[i] == null)
                    Assert.AreEqual(
                        0, outputDocument.SelectNodes(xpaths[i]).Count,
                        "Node not removed."
                        );
                else
                {
                    XmlNodeList nodes = outputDocument.SelectNodes(xpaths[i]);
                    for (int j = 0; j < nodes.Count; j++)
                    {
                        Assert.AreEqual(
                            values[i], outputDocument.SelectNodes(xpaths[i])[j].InnerText,
                            "Invalid value."
                            );
                    }
                }
            }
            return;
        }
        private void ExecuteUpdateTest(string xpath, string value)
        {
            m_TestName = "UpdateNodesTest";
            this.ExecuteUpdateTest(xpath, value, this.GetOutputPath());
            return;
        }
        private void ExecuteUpdateTest(string xpath, string value, string outputPath)
        {
            if (File.Exists(outputPath))
                File.Delete(outputPath);

            XmlHelper.UpdateNodes(xpath, value, this.SourcePathBase, outputPath);

            XmlDocument outputDocument = new XmlDocument();
            outputDocument.Load(outputPath);

            if (value == null)
                Assert.AreEqual(
                    0, outputDocument.SelectNodes(xpath).Count,
                    "Node not removed."
                    );
            else
            {
                XmlNodeList nodes = outputDocument.SelectNodes(xpath);
                for (int i = 0; i < nodes.Count; i++)
                {
                    Assert.AreEqual(
                        value, outputDocument.SelectNodes(xpath)[i].InnerText,
                        "Invalid value."
                        );
                }
            }
            return;
        }
        private string GetOutputPath()
        {
            if (string.IsNullOrEmpty(SourcePathBase))
                return null;

            return TestHelper.GetSourcePath(SourcePathBase, m_TestName);
        }

        #endregion
    }
}
